#
#	genx_transfill.py
#
#	David Janes
#	2008.08.16
#
#	GenX - search, create and insert structured data
#

import types
import urllib2

trans_typed = {
	'/common/document' : [ 'raw', 'blurb', ],
	'/common/image' : [ 'raw', 'image_thumb', ],
}
trans_uri = 'http://www.freebase.com/api/trans/%(trans_type)s%(id)s'

def transget(trans_type, id):
	uri = trans_uri % {
		"trans_type" : trans_type,
		"id" : id,
	}

	try:
		f = urllib2.urlopen(urllib2.Request(uri))
		return	f.read()
	finally:
		try: f.close()
		except: pass

def transfill(o, **ad):
	"""Add information from the Freebase/Metaweb 'trans' service to a result
	from the 'mqlread' service.

	Pass one or more of 'raw', 'blurb' or 'image_thumb' as True parameters
	to transfill to get that information whevever it would be appropriate. The
	values will be written directly into the data structure as the appropriate key.

	In order for transfill to know what can be gotten you must query the mqlread service
	first for the appropriate items. Here are a few useful query parameters:

		'/common/topic/image' : [{}],
		'/common/topic/article' : [{}],
		'/common/topic/webpage' : [{}],

	Exception handling: normally, exceptions are written into the data structure
	as if that waa a result that was read. If exception_raise is True, 
	exceptions will be raised immediately, otherwise if exception_ignore is True
	it will be as if no action was taken

	Note that this functiona and module is designed so parts can easily be
	externally replaced or upgraded if need be.

	Parameters:
	o - a result from the mqlread service (or part thereof)
	raw - read a trans 'raw' value
	blurb - read a trans 'blurb' value
	image_thumb - read a 'image_thumb' value
	exception_raise - raise exceptions
	exception_ignore - ignore exceptions

	Example:
	transfill(v, raw = True, blurb = True, image_thumb = True)

	Written by David P. Janes 2008-08-04 and placed in the public domain.
	"""
	v_id = None
	v_types = None

	if type(o) == types.DictType:
		for key, value in o.items():
			if key == 'id':
				v_id = value
			elif key == 'type':
				v_types = value
				if type(v_types) != types.ListType:
					v_types = [ v_types ]
			elif type(value) == types.ListType:
				transfill(value, **ad)

		for v_type in v_types or []:
			trans_types = trans_typed.get(v_type)
			if trans_types:
				for trans_type in trans_types:
					if ad.get(trans_type) and not o.has_key(trans_type):
						try:
							o[trans_type] = transget(trans_type = trans_type, id = v_id)
						except Exception, x:
							if ad.get('exception_raise'):
								raise	x
							elif ad.get('exception_ignore'):
								pass
							else:
								o[trans_type] = x
								

	elif type(o) == types.ListType:
		for item in o:
			transfill(item, **ad)

